/*
    Revolution Engine
    Copyright (C) 2009 Felipe Apablaza

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/


/**
 *
 *  File: Rect.hpp
 *  Desc: Rectangle class. Used in graphics operations
 *
 */

#ifndef __REVENG_MATH_RECT_HPP__
#define __REVENG_MATH_RECT_HPP__

#include <RevEng/Math/Base.hpp>
#include <RevEng/Math/Vector2.hpp>

#define REVENG_RESULT_LEFT			1
#define REVENG_RESULT_RIGHT			2
#define REVENG_RESULT_TOP			4
#define REVENG_RESULT_BOTTOM		8
#define REVENG_RESULT_INTERSECT		16

namespace RevEng
{
    namespace Math
    {
        template<typename T>
        class Rect
        {
        protected:
            Vector2<T> m_MinEdge;
            Vector2<T> m_MaxEdge;
            
        public:
            Rect();
            Rect(T X1, T Y1, T X2, T Y2);
            Rect(const Vector2<T> &Pt1, const Vector2<T> &Pt2);
            
            Rect<T> operator+ (const Vector2<T> &Vect) const;
            Rect<T> operator- (const Vector2<T> &Vect) const;
            
            Rect<T>& operator+= (const Vector2<T> &Vect);
            Rect<T>& operator-= (const Vector2<T> &Vect);
            
            bool operator == (const Rect<T> &Other) const;
            bool operator != (const Rect<T> &Other) const;
            
            Vector2<T> GetSize() const;
            Vector2<T> GetMinEdge() const;
            Vector2<T> GetMaxEdge() const;
            
            void SetSize(const Vector2<T> &Size);
            void SetMinEdge(const Vector2<T> &Edge);
            void SetMaxEdge(const Vector2<T> &Edge);
            
            void Expand(const Vector2<T> &Pt);
            
            Enum Compare(const Rect<T> &Other) const;
            
        public:
            static Rect<T> Union(const Rect<T> &Rct1, const Rect<T> &Rct2);
            static Rect<T> Intersection(const Rect<T> &Rct1, const Rect<T> &Rct2);
        };
        
        
        template<typename T>
        Rect<T>::Rect()
        {
        }
        
        
        template<typename T>
        Rect<T>::Rect(T X1, T Y1, T X2, T Y2)
        {
            if (X1 < X2)
            {
                m_MinEdge.X = X1;
                m_MaxEdge.X = X2;
            }
            else
            {
                m_MinEdge.X = X2;
                m_MaxEdge.X = X1;
            }


            if (Y1 < Y2)
            {
                m_MinEdge.Y = Y1;
                m_MaxEdge.Y = Y2;
            }
            else
            {
                m_MinEdge.Y = Y2;
                m_MaxEdge.Y = Y1;
            }
        }
        
                    
        template<typename T>
        Rect<T>::Rect(const Vector2<T> &MinEdge, const Vector2<T> &MaxEdge) : 
            m_MinEdge(MinEdge), 
            m_MaxEdge(MaxEdge)
        {
        }
        
        
        template<typename T>
        Rect<T> Rect<T>::operator+ (const Vector2<T> &Vect) const
        {
            return Rect<T>
            (
                m_MinEdge + Vect,
                m_MaxEdge + Vect
            );
        }
        
        
        
        template<typename T>
        Rect<T> Rect<T>::operator- (const Vector2<T> &Vect) const
        {
            return Rect<T>
            (
                m_MinEdge - Vect,
                m_MaxEdge - Vect
            );
        }
        
        
        
        template<typename T>
        Rect<T>& Rect<T>::operator+= (const Vector2<T> &Vect)
        {
            m_MinEdge += Vect;
            m_MaxEdge += Vect;
            
            return *this;
        }
        
        
        
        template<typename T>
        Rect<T>& Rect<T>::operator-= (const Vector2<T> &Vect)
        {
            m_MinEdge -= Vect;
            m_MaxEdge -= Vect;
            
            return *this;
        }
        
        
        
        template<typename T>
        bool Rect<T>::operator== (const Rect<T> &Other) const
        {
            if ( m_MinEdge != Other.m_MinEdge )
                return false;
                
            if ( m_MaxEdge != Other.m_MaxEdge )
                return false;
                
            return true;
        }
        
        
        
        template<typename T>
        bool Rect<T>::operator!= (const Rect<T> &Other) const
        {
            if ( m_MinEdge == Other.m_MinEdge )
                return false;
                
            if ( m_MaxEdge == Other.m_MaxEdge )
                return false;
                
            return true;
        }
        
        
        
        template<typename T>
        Vector2<T> Rect<T>::GetSize() const
        {
            return m_MaxEdge - m_MinEdge;
        }
        
        
        
        template<typename T>
        Vector2<T> Rect<T>::GetMinEdge() const
        {
            return m_MinEdge;
        }
        
        
        
        template<typename T>
        Vector2<T> Rect<T>::GetMaxEdge() const
        {
            return m_MaxEdge;
        }
        
        
        
        template<typename T>
        void Rect<T>::SetSize(const Vector2<T> &Size)
        {
            Vector2<T> MaxEdge(m_MinEdge);
            
            MaxEdge += Size;
        }
        
        
        
        template<typename T>
        void Rect<T>::SetMinEdge(const Vector2<T> &Edge)
        {
            m_MinEdge = Edge;
        }
        
        
        
        template<typename T>
        void Rect<T>::SetMaxEdge(const Vector2<T> &Edge)
        {
            m_MinEdge = Edge;
        }
        
        
        
        template<typename T>
        void Rect<T>::Expand(const Vector2<T> &Pt)
        {
            if (Pt.X < m_MinEdge.X)
                m_MinEdge.X = Pt.X;
            else
                m_MaxEdge.X = Pt.X;
                
            if (Pt.Y < m_MinEdge.Y)
                m_MinEdge.Y = Pt.Y;
            else
                m_MaxEdge.Y = Pt.Y;
        }
        
        
        
        template<typename T>
        Enum Rect<T>::Compare(const Rect<T> &Other) const
        {
            return 0;
        }
        
        
        
        template<typename T>
        Rect<T> Rect<T>::Union(const Rect<T> &Rct1, const Rect<T> &Rct2)
        {
			return Rect<T>();
        }
        
        
        
        template<typename T>
        Rect<T> Rect<T>::Intersection(const Rect<T> &Rct1, const Rect<T> &Rct2)
        {
			return Rect<T>();
        }
    }
}

#endif  //__REVENG_MATH_RECT_HPP__
